package org.career.pdung.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.career.pdung.domain.User;
import org.career.pdung.facade.UserConvester;
import org.career.pdung.form.RegistrationForm;
import org.career.pdung.manager.UserAuthenticationManager;
import org.career.pdung.serviceImpl.UserServiceImpl;
import org.career.pdung.validationForm.RegistrationValidation;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.LinkedInApi;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.api.FacebookProfile;
import org.springframework.social.facebook.api.impl.FacebookTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import sun.misc.BASE64Decoder;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.RequestToken;
@Controller
@RequestMapping("/account")
public class CreateAccountController {
	@Resource(name="userAuthenticationManager")
	private UserAuthenticationManager userAuthenticationManager;   
	public static final  String account ="account";
	@Resource(name="userConvester")
	private UserConvester userConvester;
	@Resource(name="userServiceImpl")
	private UserServiceImpl userServiceImpl;
	
	@Resource(name="registrationValidation")
	 private RegistrationValidation registrationValidation;
		
	protected static Logger logger = Logger.getLogger("controller");
	@RequestMapping(value = "/newCustomer", method = RequestMethod.GET)
	public String createCustomerForm(@RequestParam(value="error", required=false) boolean error, ModelMap model) {		
		model.addAttribute("registrationForm",new RegistrationForm());
		return account+"/createAccount";
	}
	@RequestMapping(value = "/addCustomer", method = RequestMethod.POST)
	public String addCustomer(@RequestParam(value="error", required=false) boolean error, 
			ModelMap model,@ModelAttribute("registrationForm") @Valid RegistrationForm registrationForm,BindingResult result,HttpServletRequest request) {		
		registrationValidation.validate(registrationForm, result);		
		if (result.hasErrors()) {
			return account+"/createAccount";
		} else {
			User user = new User();
			user = userConvester.doConvestFromCustomerFormToUser(registrationForm, user);
			userServiceImpl.add(user);
			autoLogin(registrationForm,request);
		}
		return "commonpage";
	}
	
	@RequestMapping(value = "/facebook", method = RequestMethod.POST)
	public String addByFaceBook( ModelMap model,HttpServletRequest request, HttpServletResponse response , final RedirectAttributes redirectModel ) {
		JSONObject payloadObject = convertSignedRequest(request, response);
		User user = null;
		try
		{
			String fbId = (String) payloadObject.getString("user_id");
			String token = (String) payloadObject.getString("oauth_token");
			Facebook facebook = new FacebookTemplate(token);
			
			FacebookProfile profile = facebook.userOperations().getUserProfile();
			String email = profile.getEmail();
			if (fbId != null && !"".equals(fbId)) 
			{			
				user = userServiceImpl.getUserByFacebookId(fbId);
				if(user != null){
					return "redirect:/auth/login";
				}
				RegistrationForm registrationForm = new RegistrationForm();
				userConvester.convertToFormFromFB(registrationForm, payloadObject,fbId);
				user = new User();
				user = userConvester.doConvestFromCustomerFormToUser(registrationForm, user);
				user.setFacebookId(registrationForm.getFacebookId());
				user.setGender(profile.getGender());				
				user.setEmail(email);
				user.setUserType("CANDIDATE");
				user.setPassWord("");
				userServiceImpl.add(user);
				user = userServiceImpl.getUserByFacebookId(fbId);
				autoLoginWithoutPassword(user, request, response);				
			}
		}
		catch (JSONException e)
		{
			System.out.println("can not get face book id from API facebook");
		}
		return "redirect:/work/home";
	}
	@RequestMapping(value = "/twitter", method = RequestMethod.GET)
	public String addByTwitter( ModelMap model,HttpServletRequest request, HttpServletResponse response , final RedirectAttributes redirectModel ) {
		/*
		 * twitter : dung.phan@sai-it.com : pass Camhuyhatinh
		 * careersitevn-22
		 */
		String consumerKey="F7bgJSXF099bXUJBSLsVcA";
		String consumerSecret="xjlafXsKoulbbWzXxdmKVyh1Uy95mWWjqQp3F0czGoU";
		Twitter twitter= new TwitterFactory().getInstance();
		twitter.setOAuthConsumer(consumerKey, consumerSecret);
		StringBuffer callbackURL = request.getRequestURL();
        int index = callbackURL.lastIndexOf("/");
        callbackURL.replace(index, callbackURL.length(), "").append("/tw/verify");
		try{
			User user = null;					
			RequestToken requestToken =twitter.getOAuthRequestToken(callbackURL.toString());
			request.getSession().setAttribute(RequestToken.class.getName(),requestToken);
			String authenUrl=requestToken.getAuthenticationURL();
			return "redirect:"+authenUrl;
			
			
		} catch(Exception ex){
			System.out.println("can not get profile from TW");
		}
		
		
		return "homepage";
	}	
	@RequestMapping(method = RequestMethod.GET,value="/tw/verify")
	public String loginWithTwitterCallback(@RequestParam(value = "oauth_verifier",required=false,defaultValue="") String oauthVerifier,
			final ModelMap model, final RedirectAttributes redirectModel,
			final HttpServletRequest request, final HttpServletResponse response, final HttpSession session)
	{
		String consumerKey="F7bgJSXF099bXUJBSLsVcA";
		String consumerSecret="xjlafXsKoulbbWzXxdmKVyh1Uy95mWWjqQp3F0czGoU";
		Twitter twitter = new TwitterFactory().getInstance();
		twitter.setOAuthConsumer(consumerKey, consumerSecret);
		RequestToken requestToken = null;
		requestToken = (RequestToken)request.getSession().getAttribute(RequestToken.class.getName());			
		twitter4j.auth.AccessToken accessToken;
		try {
			accessToken = twitter.getOAuthAccessToken(requestToken, oauthVerifier);
			twitter.setOAuthAccessToken(accessToken);
	        twitter4j.User twitterUser = twitter.verifyCredentials();
	        User user = null;
			Long userId = new Long(twitterUser.getId());
			user = userServiceImpl.getUserByTwitterId(userId.toString());
			if(user != null){
				autoLoginWithoutPassword(user, request, response);
				return "homepage";
			}
			RegistrationForm customerForm = new RegistrationForm();
			String name = twitterUser.getName();			
			customerForm.setFirstName(StringUtils.defaultIfEmpty(StringUtils.substringBefore(name, " "), name));
			customerForm.setLastName(StringUtils.defaultIfEmpty(StringUtils.substringAfter(name, " "), ""));		    
			String nickname = twitterUser.getScreenName();
			String email = nickname+"@twitter.com";
			customerForm.setEmail(email);			
			customerForm.setTwitterId(userId.toString());
			customerForm.setUserType("CANDIDATE"); 
			customerForm.setGender("MALE");
			user = new User();
			user = userConvester.doConvestFromCustomerFormToUser(customerForm, user);
			user.setPassWord("");
			user.setTwitterid(userId.toString());
			userServiceImpl.add(user);
			user = userServiceImpl.getUserByTwitterId(userId.toString());			
			autoLoginWithoutPassword(user, request, response);
			logger.info("Register with twitter successful"); 
			
		} catch (TwitterException e) {			
			e.printStackTrace();
		}
		return "homepage";
	}	
	String consumerKey="75jg5h6huko6no";
	String consumerSecret="mkWt6AV87ET9ncsq";	
	@RequestMapping(value = "/linkedin", method = RequestMethod.GET)
	public String addByLinkedin( ModelMap model,HttpServletRequest request, HttpServletResponse response , final RedirectAttributes redirectModel ) {
		StringBuffer callbackURL = request.getRequestURL();
        int index = callbackURL.lastIndexOf("/");
        callbackURL.replace(index, callbackURL.length(), "").append("/linkedin/verify");
		OAuthService service = new ServiceBuilder().provider(LinkedInApi.class).apiKey(consumerKey).apiSecret(consumerSecret)
        .callback(callbackURL.toString()).build();
		Token requestToken = service.getRequestToken();
		request.getSession().setAttribute(Token.class.getName(),requestToken);
		String authUrl = service.getAuthorizationUrl(requestToken);
		return "redirect:"+authUrl;

	}	
	@RequestMapping(method = RequestMethod.GET,value="/linkedin/verify")
	public String loginWithLinkedin(@RequestParam(value = "oauth_verifier",required=false,defaultValue="") String oauthVerifier,			
			final ModelMap model, final RedirectAttributes redirectModel,
			final HttpServletRequest request, final HttpServletResponse response, final HttpSession session)
	{	
		String PROTECTED_RESOURCE_URL =  "http://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address)";
		String scope ="r_basicprofile";
		OAuthService service = new ServiceBuilder().provider(LinkedInApi.class).apiKey(consumerKey).apiSecret(consumerSecret)
				.scope("r_emailaddress").scope(scope).build();		
		Token requestToken = (Token) request.getSession().getAttribute(Token.class.getName());
		Token accessToken = service.getAccessToken(requestToken, new Verifier(oauthVerifier));
		OAuthRequest requestData = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL);
		service.signRequest(accessToken, requestData);
		Response responseData = requestData.send();		
		String stringBody = responseData.getBody();
		User user = null;
		if(StringUtils.isNotEmpty(stringBody) && stringBody.contains("<person>")){
			String ret = XML.toJSONObject(stringBody).toString();
			JSONObject payloadObject = new JSONObject(ret);			
			JSONObject registrationJson = payloadObject.getJSONObject("person");
			if(registrationJson != null){
				String firstName = registrationJson.getString("first-name");
				String lastName =  registrationJson.getString("last-name");
				String email =  registrationJson.getString("email-address");
				String Linkedinid = registrationJson.getString("id");
				user = userServiceImpl.getUserByLinkedinId(Linkedinid);	
				if(user != null){
					autoLoginWithoutPassword(user, request, response);
					return "homepage";
				}
				RegistrationForm customerForm = new RegistrationForm();
				customerForm.setEmail(email);
				customerForm.setFirstName(firstName);
				customerForm.setLastName(lastName);	
				user = new User();
				user = userConvester.doConvestFromCustomerFormToUser(customerForm, user);
				user.setPassWord("");
				user.setLinkedinid(Linkedinid);
				user.setUserType("CANDIDATE");
				user.setGender("MALE"); 
				userServiceImpl.add(user);
				user = userServiceImpl.getUserByLinkedinId(Linkedinid);			
				autoLoginWithoutPassword(user, request, response);
				logger.info("Register with linkedin successful"); 
				
			}			
		}
		
		
		
		return "homepage";
	}


    // After successfully Creating user
    public void autoLogin(RegistrationForm registrationForm,HttpServletRequest request){    	  
    	  UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(registrationForm.getEmail(), registrationForm.getPassword());
    	  request.getSession();
    	  token.setDetails(new WebAuthenticationDetails(request));
    	  Authentication authenticatedUser = userAuthenticationManager.authenticate(token);  
    	  SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
    }
    // After successfully from social
    public void autoLoginWithoutPassword(User user,HttpServletRequest request , final HttpServletResponse response){    	  
    	  UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getEmail(),"");
    	  request.getSession();
    	  token.setDetails(new WebAuthenticationDetails(request));
    	  Authentication authenticatedUser = userAuthenticationManager.authenticate(token);  
    	  SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
    }
	@RequestMapping(method = RequestMethod.GET,value="/loginfb")
	public String loginWithFacebook(@RequestParam(value = "accessToken",required=true) String accessToken , final HttpSession session
			, final ModelMap model, final RedirectAttributes redirectModel,final HttpServletRequest request, final HttpServletResponse response) throws Exception
	{				    
        
		try {
			Facebook facebook = new FacebookTemplate(accessToken);
			FacebookProfile profile = facebook.userOperations().getUserProfile();
			String id = profile.getId();
			User user =  userServiceImpl.getUserByFacebookId(id);
			if(user == null){
				return "loginpage";
			}
			autoLoginWithoutPassword(user,request,response);
		} catch(Exception ex){
			
		}
		
		return "homepage";
	}
    
	
	
    protected JSONObject convertSignedRequest(final HttpServletRequest request, final HttpServletResponse response) {
    	String signed_request = request.getParameter("signed_request");
    	if (signed_request == null) {
    		System.out.println("ERROR: Unable to retrieve signed_request parameter");
    	    return null;
    	}
    	int count = 0;
    	String payload = null;
    	StringTokenizer st = new StringTokenizer(signed_request, ".");
    	while (st.hasMoreTokens()) {
    	    if (count == 1) {
    		payload = st.nextToken();
    		break;
    	    } else
    		st.nextToken();

    	    count++;
    	}
    	// Initialize Base64 decoder
    	
		BASE64Decoder decoder = new BASE64Decoder();
    	// Replace special character in payload as indicated by FB
    	payload = payload.replace("-", "+").replace("_", "/").trim();
    	// Decode payload
    	try {
    	    byte[] decodedPayload = decoder.decodeBuffer(payload);
    	    payload = new String(decodedPayload, "UTF8");
    	} catch (IOException e) {
    		System.out.println("ERROR: Unable to perform Base64 Decode");    		
    	    return null;
    	}

    	// JSON Decode - payload
    	JSONObject payloadObject = null;
    	try {
    	    payloadObject = new JSONObject(payload);
    	} catch (JSONException e) {
    		System.out.println("ERROR: Unable to perform JSON decode");     	
    	    return null;
    	}

    	return payloadObject;
        }  
}
